fix(compaction): recover agent config after session compaction#2378
fix(compaction): recover agent config after session compaction#2378code-yeongyu merged 11 commits intodevfrom
Conversation
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
There was a problem hiding this comment.
4 issues found across 11 files
Confidence score: 2/5
- There is a concrete compatibility risk in
src/hooks/compaction-context-injector/index.test.ts: using{ id }instead ofsessionIDforsession.promptAsynccan break URL path substitution, which is likely to cause OpenCode calls to fail rather than just a test mismatch. src/features/background-agent/compaction-aware-message-resolver.tshas two high-impact issues: synchronous read/parse of all message files can block the event loop on long sessions, and readinginfo.model?.variant(instead of rootinfo.variant) can silently skip variant-specific behavior.- Given the high severity and high confidence on multiple issues, this is likely a regression-prone merge until compatibility and performance handling are corrected.
- Pay close attention to
src/features/background-agent/compaction-aware-message-resolver.ts,src/hooks/compaction-context-injector/index.test.ts- SDK field/path mismatches and synchronous file processing may break behavior and responsiveness.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/features/background-agent/compaction-aware-message-resolver.ts">
<violation number="1" location="src/features/background-agent/compaction-aware-message-resolver.ts:53">
P1: Custom agent: **Opencode Compatibility**
The `variant` property in the OpenCode SDK is located at the root of the message object (`info.variant`), not within `model`. Reading `info.model?.variant` will silently fail to recover the agent variant from OpenCode message responses. Update the `SessionMessage` type and this mapping logic to extract `variant` directly from `info`.</violation>
<violation number="2" location="src/features/background-agent/compaction-aware-message-resolver.ts:136">
P1: Synchronously reading and parsing all message files before merging blocks the event loop and degrades performance for long sessions.</violation>
</file>
<file name="src/hooks/compaction-context-injector/index.test.ts">
<violation number="1" location="src/hooks/compaction-context-injector/index.test.ts:150">
P2: Custom agent: **Opencode Compatibility**
The OpenCode SDK defines the `tools` property on messages as `Record<string, boolean>`. The string value `"allow"` is invalid and should be a boolean (e.g., `true`).</violation>
<violation number="2" location="src/hooks/compaction-context-injector/index.test.ts:185">
P0: Custom agent: **Opencode Compatibility**
The OpenCode SDK expects the path parameter for `session.promptAsync` to be `sessionID`, not `id`. Passing `{ id }` breaks URL path substitution. Update both the test expectation and the underlying implementation.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
|
|
||
| //#then | ||
| expect(promptAsyncMock).toHaveBeenCalledWith({ | ||
| path: { id: "ses_checkpoint" }, |
There was a problem hiding this comment.
P0: Custom agent: Opencode Compatibility
The OpenCode SDK expects the path parameter for session.promptAsync to be sessionID, not id. Passing { id } breaks URL path substitution. Update both the test expectation and the underlying implementation.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/hooks/compaction-context-injector/index.test.ts, line 185:
<comment>The OpenCode SDK expects the path parameter for `session.promptAsync` to be `sessionID`, not `id`. Passing `{ id }` breaks URL path substitution. Update both the test expectation and the underlying implementation.</comment>
<file context>
@@ -104,13 +125,152 @@ describe("createCompactionContextInjector", () => {
+
+ //#then
+ expect(promptAsyncMock).toHaveBeenCalledWith({
+ path: { id: "ses_checkpoint" },
+ body: {
+ noReply: true,
</file context>
| model: { | ||
| providerID, | ||
| modelID, | ||
| ...(info.model?.variant ? { variant: info.model.variant } : {}), |
There was a problem hiding this comment.
P1: Custom agent: Opencode Compatibility
The variant property in the OpenCode SDK is located at the root of the message object (info.variant), not within model. Reading info.model?.variant will silently fail to recover the agent variant from OpenCode message responses. Update the SessionMessage type and this mapping logic to extract variant directly from info.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/features/background-agent/compaction-aware-message-resolver.ts, line 53:
<comment>The `variant` property in the OpenCode SDK is located at the root of the message object (`info.variant`), not within `model`. Reading `info.model?.variant` will silently fail to recover the agent variant from OpenCode message responses. Update the `SessionMessage` type and this mapping logic to extract `variant` directly from `info`.</comment>
<file context>
@@ -16,42 +31,121 @@ function hasFullAgentAndModel(message: StoredMessage): boolean {
+ model: {
+ providerID,
+ modelID,
+ ...(info.model?.variant ? { variant: info.model.variant } : {}),
+ },
+ }
</file context>
| continue | ||
| } | ||
| } | ||
| const messages: Array<StoredMessage | null> = [] |
There was a problem hiding this comment.
P1: Synchronously reading and parsing all message files before merging blocks the event loop and degrades performance for long sessions.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/features/background-agent/compaction-aware-message-resolver.ts, line 136:
<comment>Synchronously reading and parsing all message files before merging blocks the event loop and degrades performance for long sessions.</comment>
<file context>
@@ -16,42 +31,121 @@ function hasFullAgentAndModel(message: StoredMessage): boolean {
- continue
- }
- }
+ const messages: Array<StoredMessage | null> = []
for (const file of files) {
</file context>
| role: "user", | ||
| agent: "atlas", | ||
| model: { providerID: "openai", modelID: "gpt-5" }, | ||
| tools: { bash: "allow" }, |
There was a problem hiding this comment.
P2: Custom agent: Opencode Compatibility
The OpenCode SDK defines the tools property on messages as Record<string, boolean>. The string value "allow" is invalid and should be a boolean (e.g., true).
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/hooks/compaction-context-injector/index.test.ts, line 150:
<comment>The OpenCode SDK defines the `tools` property on messages as `Record<string, boolean>`. The string value `"allow"` is invalid and should be a boolean (e.g., `true`).</comment>
<file context>
@@ -104,13 +125,152 @@ describe("createCompactionContextInjector", () => {
+ role: "user",
+ agent: "atlas",
+ model: { providerID: "openai", modelID: "gpt-5" },
+ tools: { bash: "allow" },
+ },
+ },
</file context>
| tools: { bash: "allow" }, | |
| tools: { bash: true }, |
Retry compaction recovery when model or tool state is still incomplete, and treat reasoning or tool-only assistant progress as valid output so no-text tail recovery does not misfire.
There was a problem hiding this comment.
1 issue found across 5 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/hooks/compaction-context-injector/tail-monitor.ts">
<violation number="1" location="src/hooks/compaction-context-injector/tail-monitor.ts:1">
P1: Custom agent: **Opencode Compatibility**
The `MEANINGFUL_ASSISTANT_PART_TYPES` set is missing Opencode SDK's `"thinking"` and `"redacted_thinking"` part types. This will cause extended reasoning messages to be incorrectly treated as empty/no-text tails.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| @@ -0,0 +1,52 @@ | |||
| const MEANINGFUL_ASSISTANT_PART_TYPES = new Set([ | |||
There was a problem hiding this comment.
P1: Custom agent: Opencode Compatibility
The MEANINGFUL_ASSISTANT_PART_TYPES set is missing Opencode SDK's "thinking" and "redacted_thinking" part types. This will cause extended reasoning messages to be incorrectly treated as empty/no-text tails.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/hooks/compaction-context-injector/tail-monitor.ts, line 1:
<comment>The `MEANINGFUL_ASSISTANT_PART_TYPES` set is missing Opencode SDK's `"thinking"` and `"redacted_thinking"` part types. This will cause extended reasoning messages to be incorrectly treated as empty/no-text tails.</comment>
<file context>
@@ -0,0 +1,52 @@
+const MEANINGFUL_ASSISTANT_PART_TYPES = new Set([
+ "reasoning",
+ "tool",
</file context>
- Extract types to types.ts - Extract constants to constants.ts - Extract session ID helpers to session-id.ts - Extract recovery logic to recovery.ts hook.ts reduced from 331 to 164 LOC Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
There was a problem hiding this comment.
2 issues found across 5 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/hooks/compaction-context-injector/session-id.ts">
<violation number="1" location="src/hooks/compaction-context-injector/session-id.ts:6">
P1: Custom agent: **Opencode Compatibility**
Check for `info.sessionID` before falling back to `info.id` to prevent incorrectly returning a message ID when processing message events.</violation>
</file>
<file name="src/hooks/compaction-context-injector/recovery.ts">
<violation number="1" location="src/hooks/compaction-context-injector/recovery.ts:63">
P1: Failed recovery attempts do not update the cooldown timestamp, causing an infinite loop of prompt injections.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| return (props?.sessionID ?? | ||
| (props?.info as { id?: string } | undefined)?.id) as string | undefined |
There was a problem hiding this comment.
P1: Custom agent: Opencode Compatibility
Check for info.sessionID before falling back to info.id to prevent incorrectly returning a message ID when processing message events.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/hooks/compaction-context-injector/session-id.ts, line 6:
<comment>Check for `info.sessionID` before falling back to `info.id` to prevent incorrectly returning a message ID when processing message events.</comment>
<file context>
@@ -0,0 +1,8 @@
+}
+
+export function resolveSessionID(props?: Record<string, unknown>): string | undefined {
+ return (props?.sessionID ??
+ (props?.info as { id?: string } | undefined)?.id) as string | undefined
+}
</file context>
| return (props?.sessionID ?? | |
| (props?.info as { id?: string } | undefined)?.id) as string | undefined | |
| return (props?.sessionID ?? | |
| (props?.info as { sessionID?: string } | undefined)?.sessionID ?? | |
| (props?.info as { id?: string } | undefined)?.id) as string | undefined |
| } | ||
| } | ||
|
|
||
| try { |
There was a problem hiding this comment.
P1: Failed recovery attempts do not update the cooldown timestamp, causing an infinite loop of prompt injections.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/hooks/compaction-context-injector/recovery.ts, line 63:
<comment>Failed recovery attempts do not update the cooldown timestamp, causing an infinite loop of prompt injections.</comment>
<file context>
@@ -0,0 +1,143 @@
+ }
+ }
+
+ try {
+ await ctx.client.session.promptAsync({
+ path: { id: sessionID },
</file context>
Summary
Testing
bun test src/hooks/compaction-context-injector/index.test.ts src/features/background-agent/compaction-aware-message-resolver.test.ts src/index.test.ts src/hooks/preemptive-compaction.test.ts src/hooks/compaction-todo-preserver/index.test.tsbun test src/features/background-agent/manager.test.ts src/features/background-agent/manager.polling.test.tsbun run typecheckbun testbun run buildSummary by cubic
Restores session agent/model/tools after compaction via checkpointing and compaction-aware context merging; validates recovery and retries; prevents false “no-text” tail triggers. Addresses issue-2232.
Bug Fixes
Refactors
Written for commit 3550305. Summary will update on new commits.